#include "../include/Sock.h"
#include "../include/global.h"
//#include "../include/SockIO.h"
#include "../include/SocketEpoll.h"
#include "../include/exception/SocketException.h"


extern "C" {
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
}

namespace ZY {

    map<int,Sock *> Sock::m_map;
    list<Sock *> Sock::m_close_list;
    time_t Sock::_heartCheckTime(0);
//    map<int, void(*)( Sock &)> Sock::m_events;

    //const int Sock::EVENT_CLOSE         = 0;
//    const int Sock::EVENT_INIT             = 1;
//    const int Sock::EVENT_DESTORY     = 2;
    const int Sock::EVENT_ACCPET        = 3;
//    const int Sock::EVENT_WRITE_EMPTY = 4;

    void Sock::_Sock( int _domain , int _type , int _protocol )
    {
        //ctor

        fd = socket( _domain , _type , _protocol );

        if ( fd < 0 )
        {
            //throw
            //throw runtime_error( "Can't Create Socket!" );
            throw SocketException( "Can't Create Socket!" , 10001 );
        }
        Sock::m_map[fd] = this;
        _needDelete = true;
        setActive();

//        if ( event_exists( EVENT_INIT ) ) {
//            m_events[EVENT_INIT]( *this );
//        }
        /*** todo :
        io = new SockIO( *this , se );
        */
        //m_cmd = new CmdExec( *this );
//        io = NULL;
    }

    Sock::Sock( int i_fd  ) :
//        io(NULL) ,
        write_data( _writeByteStringObject.getDataStringQuote() ) ,
        write_data_offset( _writeByteStringObject.getDataStringReadOffsetQuote() )
    {
        this->fd = i_fd;
        Sock::m_map[i_fd] = this;
        setActive();
        _needDelete = true;
//        if ( event_exists( EVENT_INIT ) ) {
//            m_events[EVENT_INIT]( *this );
//        }
        /*** todo :
        io = new SockIO( *this , se );
        */
        //m_cmd = new CmdExec( *this );

    }

    Sock::Sock(bool _value):
        write_data( _writeByteStringObject.getDataStringQuote() ) ,
        write_data_offset( _writeByteStringObject.getDataStringReadOffsetQuote() )
    {


        fd = socket( AF_INET,SOCK_STREAM,0 );

        if ( fd < 0 )
        {
            //throw
            //throw runtime_error( "Can't Create Socket!" );
            throw SocketException( "Can't Create Socket!" , 10001 );
        }
        _needDelete = _value;
        if(_value){
            Sock::m_map[fd] = this;
        }

        setActive();
    }

    Sock::~Sock()
    {
        //dtor

//        if ( event_exists( EVENT_DESTORY ) ) {
//            m_events[ EVENT_DESTORY ]( *this );
//        }

        Event ev;
        ev.ptr = this;
        callEventListener( EVENT::EVENT_DESTORY , & ev );
        //cout<<"close fd"<<fd<<endl;
        if ( fd >= 0 ) {

            close( fd );
            if ( m_map.count( fd ) > 0 ) {
                m_map.erase( fd );
            }
        }


        /** todo :
        delete io;
        */
        //delete m_cmd;
    }



    bool Sock::bindAndListen( in_port_t i_port , uint16_t listenq )
    {
        struct sockaddr_in servaddr ;

        memset( & servaddr , 0 , sizeof( servaddr ) );

        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons( i_port );
        servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
        if ( bind( fd ,(struct sockaddr *)& servaddr,sizeof(servaddr))<0)
        {
            //printf("bind failed.\n");
            return false;
        }

        status[0] = 1;

        if ( listen( fd , listenq ) == 0 ) {
            return true;
        } else {
            return false;
        }
    }

    bool Sock::bindAndListen( in_port_t port )
    {
        return this->bindAndListen( port , LISTENQ );
    }

//    void Sock::NewIO( SocketEpoll &s )
//    {
//        io = new SockIO( *this , s );
//    }
//
//    void Sock::DeleteIO()
//    {
//        if ( io ) {
//            delete io;
//        }
//        io = NULL;
//    }

    bool Sock::ConnectDomain( string domain , in_port_t port )
    {
        char str[32];

        struct hostent *hptr;
        hptr = gethostbyname( domain.c_str() );
        if ( ! hptr )  {
            return false;
        }
        string ip( inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str))) ;
        return Connect( ip , port );
    }

    /**
        连接另一台服务器
    **/
    bool Sock::Connect( string ip , in_port_t port )
    {
        struct sockaddr_in addr;
        memset( & addr , 0 , sizeof( addr ) );
        addr.sin_family = AF_INET;
        addr.sin_port = htons( port );
        addr.sin_addr.s_addr = inet_addr( ip.c_str() );

        int ret = connect ( fd , ( struct sockaddr*) & addr , sizeof( addr ) );

        if ( ret < 0 ) {
            //cout << "ERROR:" << errstr( ret ) << endl;
            return false ;
        } else {
            status[1] = 1;
            return true;
        }
    }

    void Sock::Accept()
    {
        if ( ! status[0] ) {
            //throw runtime_error( "Not Linstener Fd!" );
            throw SocketException( "Not Linstener Fd!" , 10002 );
        }

        int connfd ;
        struct sockaddr_in cliaddr;
        socklen_t len;
        Sock *sock;

        len = sizeof( cliaddr );
        while(1) {
            connfd = accept( fd ,(struct sockaddr *)&cliaddr,&len );
            if ( connfd < 0 ) {
                switch( errno ) {
                    case EINTR: //有信号发生
                        continue;
                    case EAGAIN: //未获取到数据(非阻塞时出现)
                    case EBADF: //描述符无效
                    case ENFILE:
                    case EMFILE:
                    default:
                        return;
                }
            }

            //生成新的Socket对象
            sock = new Sock( connfd );

            sock->setStatus(2,true);

//            if ( event_exists( EVENT_ACCPET ) ) {
//                m_events[ EVENT_ACCPET ] ( *sock );
//            }

            {
                Event ev;
                ev.ptr = sock;
                callEventListener( EVENT::EVENT_ACCPET , & ev );
            }



            /** todo :
            sock->setNonblock();
            se.insert( sock );
            */
        }
    }

    Sock *Sock::getPointer( int i_fd )
    {
        if ( m_map.count( i_fd ) == 0 ) {
            return NULL;
        }
        return m_map[i_fd];
    }

    void Sock::heartCheck( int activeTimeout )
    {
        map<int,Sock*>::iterator m_iter;
        Sock *sock;
        time_t t;

        t = time(NULL);
        if ( t - _heartCheckTime < HEAR_CHECK_TIMEOUT ) {
            return;
        } else {
            _heartCheckTime = t;
        }

        for( m_iter = m_map.begin() ; m_iter != m_map.end() ; m_iter ++ ) {
            sock = m_iter->second;
            if ( sock->getStatus(2) && t - sock->getActive() > activeTimeout ) {
                //心跳超时，关闭
                sock->Close();
            }
        }
    }

    void Sock::heartCheck()
    {
        heartCheck( ACTIVE_TIMEOUT );
    }

    void Sock::CloseListCheck()
    {
        list<Sock*>::iterator iter;

        iter = Sock::m_close_list.begin() ;

        while( iter != Sock::m_close_list.end() ) {
            if ( (*iter)->getStatus(5) ) {
                delete( *iter );
            }else{
                cout<<"status error"<<endl;
            }
            iter = Sock::m_close_list.erase( iter );
        }
    }

    bool Sock::_Close()
    {
//        if ( m_map.count( fd ) > 0 ) {
//            m_map.erase( fd );
//        }
//        if(getStatus(5)){
//            return true;
//        }
        setStatus(5,true);
        setStatus(1,false);

        if(needDelete()){
            Sock::m_close_list.push_back( this );
        }else{
            cout<<"push into close list error"<<endl;
        }



        return true;
    }

    //关闭
    bool Sock::Close()
    {
        if ( ! status[5] ) {
            status[5] = 1;
//            if ( event_exists( EVENT_CLOSE ) ) {
//                m_events[ EVENT_CLOSE ]( *this );
//                return true;
//            }

            Event ev;
            ev.ptr = this;

            if ( callEventListener( EVENT::EVENT_CLOSE , & ev ) ) {
                return true;
            }
            return _Close();
        } else {
            return false;
        }
    }

//    void Sock::event_register( int event_code , void(*func)(Sock&) )
//    {
//        m_events[event_code] = func;
//    }
//    void Sock::event_unregister( int event_code )
//    {
//        m_events.erase( event_code );
//    }
//    bool Sock::event_exists( int event_code )
//    {
//        return m_events.count( event_code ) > 0 ;
//    }

    bool Sock::readAll()
    {
        int n ;

//        if(isLocked()){
//            return false;
//        }

        while( 1 ) {
            if ( status[5] ) {
                n = 0;
            } else {
                n = read( fd , readbuff , IO_BUFF_MAX_SIZE );
            }

            if ( n > 0 ) {
    //            read_data.append( readbuff , n );
                _readByteStringObject.setCharArray( readbuff , n );
            } else if ( n < 0 ) {
                switch ( errno ) {
                    case EINTR: //有信号发生，继续读取
                        continue;
                    case EAGAIN: //没有数据可用，返回
                        return true;
                    default:
                        //出现错误，应该关闭
                        //status[5] = 1;
                        Close();
                        throw SocketException("Socket ERROR.Closed");
                        //return;
                }
            } else {
                //断线处理
                //status[5] = 1;
                Close();
                return false;
                //throw SocketException("Socket Closed!");
                //return;
            }
        }
    }

    bool Sock::writeAll()
    {
         char *buff ;
         int n , len , s;

         s = write_data.length() ;
         len = s - write_data_offset;

        if ( len == 0 ) {
            Event ev;
            ev.ptr = (void*) this;
//            callStaticEventListener( EVENT::EVENT_WRITE_EMPTY , & ev );
            callEventListener( EVENT::EVENT_WRITE_EMPTY , & ev );
           /// se.updateToIn( sock );
            return true;
        }

    //     char data[s];
    //
    //     memcpy( data , write_data.data() + write_data_offset , s );

         char *data;
         data = (char*) write_data.data();

         //fd = sock->getFd();

         while ( true ) {
                buff = data + write_data_offset;
                if ( status[5] ) {
                    n = len;
                } else {
                    n = write( fd ,  buff , len );
                }

                if ( n < 0 ) {
                    switch( errno ) {
                        case EINTR ://有信号发生，继续
                            continue;
                        case ENOBUFS :
                        case EAGAIN ://缓冲区满，退出处理，等待下一次请求到达，再继续处理:
                            //转为写模式
                            status[4] = 1;
                            {
                                Event ev;
                                ev.ptr = (void*) this;
                                //callStaticEventListener( EVENT::EVENT_WRITE_NOBUFS , & ev );
                                callEventListener( EVENT::EVENT_WRITE_NOBUFS , & ev );
                            }

                            ///se.updateToOut( sock );
                            goto while_out;
                        case ENOTCONN: //关闭连接
                        case EPIPE:
                        default://其它错误，中断处理??????????这里有问题，这里会停止发送信息，需要将错误处理细化
//                            status[5] = 1;

                            cout << "WRITE Error: " << strerror( errno ) << endl;

                            Close();


                            //return false;
                            return false;
                            //throw SocketException("Socket ERROR,Closed!");
                            //return;
                    }
                } else if ( n > 0 ) {
                    write_data_offset += n;
                    len -= n;
                    if ( len <= 0 ) {
                        //发送完毕，退出
                        ///se.updateToIn( sock );
                        Event ev;
                        ev.ptr = (void*) this;
                        //callStaticEventListener( EVENT::EVENT_WRITE_EMPTY , & ev );
                        callEventListener( EVENT::EVENT_WRITE_EMPTY , & ev );
                        break;
                    }
                    //继续写入
                } else {
                    Close();
                    //throw SocketException("Socket Closed!");
                    return false;
                    //return;
                }
         }

while_out:

         if ( write_data_offset > DATA_RESET_MAX_OFFSET ) {
            _writeByteStringObject.zip();
         }

         return true;
    }

    //判断是否正在发送中，如果不是发送中。则进行数据发送
    void Sock::send()
    {
        if ( ! status[4] ) { //未发送状态
            try {
                writeAll();
            } catch ( SocketException ) {

            }
        }
    }

    void Sock::nativeSend( string &str )
    {
        _writeByteStringObject.setString( str );

        if ( ! status[4] ) { //未发送状态
            try {
                writeAll();
            } catch ( SocketException ) {

            }
        }
    }

    //判断是否正在发送中，如果不是发送中。则进行数据发送
    void Sock::send( ByteString & bs )
    {
        string str( bs.getDataString() );

        _writeByteStringObject.setUnsignedInt32( str.length() )->setString( str );

        if ( ! status[4] ) { //未发送状态
            try {
                writeAll();
            } catch ( SocketException ) {

            }

        }
    }

    ByteString &Sock::getReadByteStringObject()
    {
        return _readByteStringObject;
    }

    ByteString &Sock::getWriteByteStringObject()
    {
        return _writeByteStringObject;
    }

    bool Sock::isLocked()
    {
        return status.test(7);
    }

    bool Sock::lockSocket()
    {
        status.set(7,true);
        return true;
    }

    bool Sock::unlockSocket()
    {
        status.set(7,false);
        return true;
    }

    bool Sock::needDelete()
    {
        return _needDelete;
    }
}
